﻿#region <!-- Using Directives -->

using System;
using System.IO;
using System.Windows.Forms;
using System.Xml;
using WordSharpDev.Controls;
using WordSharpDev.Extensions;
using WordSharpDev.Properties;
using WordSharpDev.Utils;
using Clipboard = System.Windows.Clipboard;
using Office = Microsoft.Office.Core;

using Word = Microsoft.Office.Interop.Word;

using WindowEventArgs = Microsoft.Office.Tools.Word.WindowEventArgs;
using SelectionEventArgs = Microsoft.Office.Tools.Word.SelectionEventArgs;

#endregion

namespace WordSharpDev
{
	public partial class ThisDocument
	{
		private String m_LastDoc;

		private FileInfo m_TempFile;
		private FileInfo m_DocumentFile;

		#region <!-- EnableEvents -->

		public Boolean EnableEvents { get; set; }

		#endregion

		#region <!-- Document: Prop -->

		public String Properties
		{
			get
			{
				var l_Result = Share.UIAppPane.DocumentProperties;

				return l_Result.IsValidXml() ? l_Result : "";
			}

			private set
			{
				var l_Result = value;

				Share.UIAppPane.DocumentProperties = l_Result.IsValidXml() ? l_Result : "";
			}
		}

		#endregion

		#region <!-- Document: Code -->

		private String CodeDescription
		{
			get
			{
				var l_Result = Share.UIAppPane.CodeDescription;

				return l_Result.IsValidXml() ? l_Result : "";
			}

			set
			{
				var l_Result = value;

				Share.UIAppPane.CodeDescription = l_Result.IsValidXml() ? l_Result : "";
			}
		}

		private Word.Table CodeTarget
		{
			get
			{
				return Share.UIAppPane.CodeTarget;
			}

			set
			{
				Share.UIAppPane.CodeTarget = value;
			}
		}

		#endregion

		#region <!-- Document: IsSaved -->

		private Boolean m_IsSaved;

		public Boolean IsSaved
		{
			get { return m_IsSaved; }
			private set { Share.UIAppPane.IsDocumentSaved = Saved = m_IsSaved = value; }
		}

		#endregion

		#region <!-- Document: Startup -->

		private void ThisDocument_Startup(Object p_Sender, EventArgs p_Args)
		{
			#region <!-- Remove attached template -->

			AttachedTemplate = null;

			#endregion

			#region <!-- Save current document -->

			m_TempFile = Root.GetTempFile("WordSharpTemp.docx");

			m_DocumentFile = Root.GetTempFile("WordSharpStudio.docx");

			SaveAs(m_DocumentFile.FullName);

			#endregion

			#region <!-- Set up action pane -->

			ActionsPane.Controls.Add(Share.UIAppPane);

			Share.UIAppPane.Dock = DockStyle.Fill;

			#endregion

			#region <!-- Handle events -->

			Deactivate += ThisDocument_Deactivate;

			ActivateEvent += ThisDocument_ActivateEvent;

			SelectionChange += ThisDocument_SelectionChange;

			ContentControlAfterAdd += ThisDocument_ContentControlAfterAdd;

			ContentControlBeforeDelete += ThisDocument_ContentControlBeforeDelete;

			Share.UIAppPane.OnDocPropChange += ThisDocument_DocPropChange;

			Share.UIAppPane.OnCodeDescChange += ThisDocument_CodeDescChange;

			Application.DocumentOpen += Application_DocumentOpen;

			Application.DocumentBeforeSave += Application_DocumentBeforeSave;

			Application.DocumentBeforeClose += Application_DocumentBeforeClose;

			#endregion

			Share.UIAppPane.WriteDetailLogs("Welcome!");

			LoadDocument(Resources.GetDocument("BaseDocument"));

			EnableEvents = true;
		}

		#endregion

		#region <!-- Document: Shutdown -->

		private void ThisDocument_Shutdown(Object p_Sender, EventArgs p_Args)
		{
			Clipboard.Clear();

			Saved = true;
		}

		#endregion

		#region <!-- Document: Activate -->

		private void ThisDocument_ActivateEvent(Object p_Sender, WindowEventArgs p_Args)
		{
			if (!EnableEvents) return;

			Update();
		}

		#endregion

		#region <!-- Document: Deactivate -->

		private void ThisDocument_Deactivate(Object p_Sender, WindowEventArgs p_Args)
		{
			if (!EnableEvents) return;

			Update();
		}

		#endregion

		#region <!-- Document: SelectionChange -->

		private void ThisDocument_SelectionChange(Object p_Sender, SelectionEventArgs p_Args)
		{
			if (!EnableEvents) return;

			Update();

			Share.UIAppPane.ShowDocumentTab();

			CodeDescription = "";

			foreach (Word.Table i_Table in Tables)
			{
				if (p_Args.Selection.InRange(i_Table.Range))
				{
					var l_Node = i_Table.Descr.AsXmlNode();

					if (l_Node != null && l_Node.Name.IsLikeFull("Code"))
					{
						CodeDescription = l_Node.OuterXml;
						CodeTarget = i_Table;

						CodeTarget.Shading.BackgroundPatternColor = Word.WdColor.wdColorLightYellow;

						Share.UIAppPane.ShowCodeTab();
					}

					break;
				}
			}

			if (CodeDescription == "" && CodeTarget != null)
			{
				CodeTarget.Shading.BackgroundPatternColor = Word.WdColor.wdColorWhite;
				CodeTarget = null;
			}
		}

		#endregion

		#region <!-- Document: ContentControlAfterAdd -->

		private void ThisDocument_ContentControlAfterAdd(Word.ContentControl p_NewContentControl, Boolean p_InUndoRedo)
		{
			if (!EnableEvents) return;

			Update();
		}

		#endregion

		#region <!-- Document: ContentControlBeforeDelete -->

		private void ThisDocument_ContentControlBeforeDelete(Word.ContentControl p_OldContentControl, Boolean p_InUndoRedo)
		{
			if (!EnableEvents) return;

			Update();
		}

		#endregion

		#region <!-- Document: DocPropChange -->

		private void ThisDocument_DocPropChange()
		{
			if (!EnableEvents) return;

			//SetCustomPropertyString("Source", Properties);
		}

		#endregion

		#region <!-- Document: CodeDescChange -->

		private void ThisDocument_CodeDescChange()
		{
			if (!EnableEvents) return;

			CodeTarget.Descr = CodeDescription;
		}

		#endregion

		#region <!-- Application: DocumentOpen -->

		private void Application_DocumentOpen(Word.Document p_Document)
		{
		}

		#endregion

		#region <!-- Application: DocumentBeforeSave -->

		private void Application_DocumentBeforeSave(Word.Document p_Document, ref Boolean p_UI, ref Boolean p_Cancel)
		{
			if (!EnableEvents) return;

			var l_EnableEvents = EnableEvents;
			var l_DisplayAlerts = Application.DisplayAlerts;
			var l_ScreenUpdating = Application.ScreenUpdating;

			EnableEvents = false;
			Application.DisplayAlerts = Word.WdAlertLevel.wdAlertsNone;
			Application.ScreenUpdating = false;

			var l_Exception = new ErrException("Could not save document");

			try
			{
				Share.UIDialogChoice = 0;

				Share.UIAppPane.SwitchStatusWait();

				Share.UIAppPane.WriteMainLogs("Saving document...");

				Share.UIAppPane.WriteDetailLogs("Saving document...");

				if (!Properties.IsVoid())
				{
					if (!m_LastDoc.IsVoid() && m_LastDoc != Properties)
					{
						if (Share.Project.ExistDocument(Properties.AsXmlNode()))
						{
							var l_Dialog = new WordSharpBox<DialogBox>();

							l_Dialog.Child.Message = "Document already exists. What would you like to do?";

							l_Dialog.Child.AddChoice("Overwrite", true);
							l_Dialog.Child.AddChoice("Rename", false);
							l_Dialog.Child.AddChoice("Cancel", true);

							l_Dialog.Width = 360;
							l_Dialog.Height = 180;

							l_Dialog.ShowDialog(Share.GetAppRect());

							Share.UIDialogChoice = l_Dialog.Child.SelectedIndex;
						}
						else
						{
							var l_Dialog = new WordSharpBox<DialogBox>();

							l_Dialog.Child.Message = "New document. What would you like to do?";

							l_Dialog.Child.AddChoice("Duplicate", true);
							l_Dialog.Child.AddChoice("Rename", false);
							l_Dialog.Child.AddChoice("Cancel", true);

							l_Dialog.Width = 360;
							l_Dialog.Height = 180;

							l_Dialog.ShowDialog(Share.GetAppRect());

							Share.UIDialogChoice = l_Dialog.Child.SelectedIndex;
						}
					}

					if (Share.UIDialogChoice == 0 || Share.UIDialogChoice == 1)
					{
						var l_TempDocument = Application.Documents.Add(DocumentType: Word.WdNewDocumentType.wdNewBlankDocument, Visible: false);

						l_TempDocument.StoryRanges[Word.WdStoryType.wdMainTextStory].PasteFrom(StoryRanges[Word.WdStoryType.wdMainTextStory]);
						l_TempDocument.StoryRanges[Word.WdStoryType.wdPrimaryHeaderStory].PasteFrom(StoryRanges[Word.WdStoryType.wdPrimaryHeaderStory]);

						l_TempDocument.SetCustomPropertyString("Source", Properties);

						l_TempDocument.SaveAs(FileName: m_TempFile.FullName);

						((Word._Document)l_TempDocument).Close(SaveChanges: Word.WdSaveOptions.wdDoNotSaveChanges);

						Share.Project.SaveDocument(Properties.AsXmlNode(), m_TempFile.FullName);

						Share.UIAppPane.WriteDetailLogs("Saving document... done");

						Share.UIAppPane.WriteMainLogs("Saving document... done");

						Share.UIAppPane.SwitchStatusReady();

						m_LastDoc = Properties;

						IsSaved = true;
					}
					else
					{
						Share.UIAppPane.WriteDetailLogs("Saving document... cancel");

						Share.UIAppPane.WriteMainLogs("Saving document... cancel");

						Share.UIAppPane.SwitchStatusReady();
					}
				}
				else
				{
					l_Exception.AppendChildException("Valid xml document properties expected");

					throw l_Exception;
				}
			}
			catch (Exception e)
			{
				l_Exception.AppendChildException(e);

				Share.UIAppPane.WriteDetailLogs(Share.FormatException(l_Exception));

				Share.UIAppPane.WriteMainLogs("Saving document... error");

				Share.UIAppPane.SwitchStatusError();

				IsSaved = false;
			}
			finally
			{
				Share.UIAppPane.ReloadDocumentCount();

				Share.UIAppPane.NotifyDocumentMerged(Properties.AsXmlNode());

				Share.UIAppPane.NotifyDocumentSelected(Properties.AsXmlNode());

				EnableEvents = l_EnableEvents;
				Application.DisplayAlerts = l_DisplayAlerts;
				Application.ScreenUpdating = l_ScreenUpdating;
			}
		}

		#endregion

		#region <!-- Application: DocumentBeforeClose -->

		private void Application_DocumentBeforeClose(Word.Document p_Document, ref Boolean p_Cancel)
		{
			p_Document.Saved = true;
		}

		#endregion

		#region <!-- Update -->

		public void Update()
		{
			Application.CommandBars["Task Pane"].Visible = true;

			if (!Saved) IsSaved = false;
		}

		#endregion

		#region <!-- SaveAs -->

		public void SaveCopyAs(String p_FileName)
		{
			var l_EnableEvents = EnableEvents;

			EnableEvents = true;

			Save();

			m_TempFile.CopyTo(p_FileName, true);

			EnableEvents = l_EnableEvents;
		}

		private void SaveAs(String p_FileName)
		{
			Object l_FileName = p_FileName;

			SaveAs(ref l_FileName, ref Root.Missing, ref Root.Missing, ref Root.Missing, ref Root.Missing, ref Root.Missing, ref Root.Missing, ref Root.Missing, ref Root.Missing, ref Root.Missing, ref Root.Missing, ref Root.Missing, ref Root.Missing, ref Root.Missing, ref Root.Missing, ref Root.Missing);
		}

		#endregion

		#region <!-- LoadData -->

		public void LoadData(XmlNode p_Key)
		{
			var l_EnableEvents = EnableEvents;
			var l_DisplayAlerts = Application.DisplayAlerts;
			var l_ScreenUpdating = Application.ScreenUpdating;

			EnableEvents = false;
			Application.DisplayAlerts = Word.WdAlertLevel.wdAlertsNone;
			Application.ScreenUpdating = false;

			var l_Exception = new ErrException("Could not load data");

			try
			{
				Share.UIDialogChoice = 0;

				Share.UIAppPane.SwitchStatusWait();

				Share.UIAppPane.WriteMainLogs("Loading data...");

				Share.UIAppPane.WriteDetailLogs("Loading data...");

				Share.Project.ExtractDocument(p_Key, m_TempFile.FullName);

				var l_SourceDocument = Application.Documents.Open(m_TempFile.FullName, ReadOnly: true, Visible: false);

				var l_DocumentProperties = l_SourceDocument.GetCustomPropertyString("Source");

				if (l_DocumentProperties.IsValidXml())
				{
					StoryRanges[Word.WdStoryType.wdMainTextStory].PasteFrom(l_SourceDocument.StoryRanges[Word.WdStoryType.wdMainTextStory]);

					StoryRanges[Word.WdStoryType.wdPrimaryHeaderStory].PasteFrom(l_SourceDocument.StoryRanges[Word.WdStoryType.wdPrimaryHeaderStory]);
					//StoryRanges[Word.WdStoryType.wdPrimaryFooterStory].PasteFrom(l_SourceDocument.StoryRanges[Word.WdStoryType.wdPrimaryFooterStory]);

					Properties = l_DocumentProperties;

					CodeDescription = "";

					Share.UIAppPane.WriteDetailLogs("Loading data... done");

					Share.UIAppPane.WriteMainLogs("Loading data... done");

					Share.UIAppPane.SwitchStatusReady();

					IsSaved = true;
				}
				else
				{
					((Word._Document)l_SourceDocument).Close();

					l_Exception.AppendChildException("Valid xml document properties expected");

					throw l_Exception;
				}

				((Word._Document)l_SourceDocument).Close();
			}
			catch (Exception e)
			{
				l_Exception.AppendChildException(e);

				Share.UIAppPane.WriteDetailLogs(Share.FormatException(l_Exception));

				Share.UIAppPane.WriteMainLogs("Loading data... error");

				Share.UIAppPane.SwitchStatusError();
			}
			finally
			{
				Share.UIAppPane.NotifyDocumentSelected(Properties.AsXmlNode());

				EnableEvents = l_EnableEvents;
				Application.DisplayAlerts = l_DisplayAlerts;
				Application.ScreenUpdating = l_ScreenUpdating;
			}
		}
		
		#endregion

		#region <!-- LoadDocument -->

		public void LoadDocument(String p_FileName)
		{
			var l_EnableEvents = EnableEvents;
			var l_DisplayAlerts = Application.DisplayAlerts;
			var l_ScreenUpdating = Application.ScreenUpdating;

			EnableEvents = false;
			Application.DisplayAlerts = Word.WdAlertLevel.wdAlertsNone;
			Application.ScreenUpdating = false;

			var l_Exception = new ErrException("Could not load document");

			try
			{
				Share.UIDialogChoice = 0;

				Share.UIAppPane.SwitchStatusWait();

				Share.UIAppPane.WriteMainLogs("Loading document...");

				Share.UIAppPane.WriteDetailLogs("Loading document...");

				var l_SourceDocument = Application.Documents.Open(p_FileName, ReadOnly: true, Visible: false);

				var l_DocumentProperties = l_SourceDocument.GetCustomPropertyString("Source");

				if (l_DocumentProperties.IsValidXml())
				{
					StoryRanges[Word.WdStoryType.wdMainTextStory].PasteFrom(l_SourceDocument.StoryRanges[Word.WdStoryType.wdMainTextStory]);

					StoryRanges[Word.WdStoryType.wdPrimaryHeaderStory].PasteFrom(l_SourceDocument.StoryRanges[Word.WdStoryType.wdPrimaryHeaderStory]);
					//StoryRanges[Word.WdStoryType.wdPrimaryFooterStory].PasteFrom(l_SourceDocument.StoryRanges[Word.WdStoryType.wdPrimaryFooterStory]);

					Properties = l_DocumentProperties;

					CodeDescription = "";

					Share.UIAppPane.WriteDetailLogs("Loading document... done");

					Share.UIAppPane.WriteMainLogs("Loading document... done");

					Share.UIAppPane.SwitchStatusReady();

					IsSaved = false;
				}
				else
				{
					((Word._Document)l_SourceDocument).Close();

					l_Exception.AppendChildException("Valid xml document properties expected");

					throw l_Exception;
				}

				((Word._Document)l_SourceDocument).Close();
			}
			catch (Exception e)
			{
				l_Exception.AppendChildException(e);

				Share.UIAppPane.WriteDetailLogs(Share.FormatException(l_Exception));

				Share.UIAppPane.WriteMainLogs("Loading document... error");

				Share.UIAppPane.SwitchStatusError();
			}
			finally
			{
				EnableEvents = l_EnableEvents;
				Application.DisplayAlerts = l_DisplayAlerts;
				Application.ScreenUpdating = l_ScreenUpdating;
			}
		}

		#endregion

		#region <!-- BuiltInPropertyString -->

		//private String GetBuiltInPropertyString(Word.WdBuiltInProperty p_Name)
		//{
		//	return WordExtensions.GetBuiltInPropertyString(this, p_Name);
		//}

		//private void SetBuiltInPropertyString(Word.WdBuiltInProperty p_Name, String p_Value)
		//{
		//	WordExtensions.SetBuiltInPropertyString(this, p_Name, p_Value);
		//}

		//private void CopyBuiltInPropertyStringTo(Word.Document p_Document, Word.WdBuiltInProperty p_Name)
		//{
		//	p_Document.SetBuiltInPropertyString(p_Name, GetBuiltInPropertyString(p_Name));
		//}

		//private void CopyBuiltInPropertyStringFrom(Word.Document p_Document, Word.WdBuiltInProperty p_Name)
		//{
		//	SetBuiltInPropertyString(p_Name, p_Document.GetBuiltInPropertyString(p_Name));
		//}

		#endregion

		#region <!-- CustomPropertyString -->

		//private String GetCustomPropertyString(String p_Name)
		//{
		//	return WordExtensions.GetCustomPropertyString(this, p_Name);
		//}

		//private void SetCustomPropertyString(String p_Name, String p_Value)
		//{
		//	WordExtensions.SetCustomPropertyString(this, p_Name, p_Value);
		//}

		//private void CopyCustomPropertyStringTo(Word.Document p_Document, String p_Name)
		//{
		//	p_Document.SetCustomPropertyString(p_Name, GetCustomPropertyString(p_Name));
		//}

		//private void CopyCustomPropertyStringFrom(Word.Document p_Document, String p_Name)
		//{
		//	SetCustomPropertyString(p_Name, p_Document.GetCustomPropertyString(p_Name));
		//}

		#endregion

		#region <!-- Internal -->

		//Startup += ThisDocument_Startup;
		//Shutdown += ThisDocument_Shutdown;

		private void InternalStartup()
		{
			Startup += ThisDocument_Startup;
			Shutdown += ThisDocument_Shutdown;
		}

		#endregion

		#region <!-- Ribbon -->

		protected override Office.IRibbonExtensibility CreateRibbonExtensibilityObject()
		{
			return new WordSharpRibbon();
		}

		#endregion
	}
}